package com.tbit.uqbike.service.business.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.tbit.uqbike.annos.EncapsulateMap;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.Account;
import com.tbit.uqbike.object.pojo.MoneyData;
import com.tbit.uqbike.object.pojo.WeixinDepositLog;
import com.tbit.uqbike.object.pojo.vo.DeptPayVO;
import com.tbit.uqbike.object.value.FinaStat;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.business.FinaStatService;
import com.tbit.uqbike.webmanager.dao.core.*;
import com.tbit.uqbike.webmanager.dao.log.RefundOpeLogDao;
import com.tbit.uqbike.webmanager.dao.stat.*;
import com.tbit.uqbike.webmanager.util.StringUtil;
import com.tbit.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: chen
 * @Description:
 * @Date: 创建于 13:53 2020/6/30
 */
@Service
@Slf4j
public class FinaStatServiceImpl implements FinaStatService {
    @Autowired
    private RideCardDao rideCardDao;
    @Autowired
    private RideLogDao rideLogDao;
    @Autowired
    private MemberFeeDao memberFeeDao;
    @Autowired
    private UserToAgentDao userToAgentDao;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private WeixinDepositLogDao weixinDepositLogDao;
    @Autowired
    private VipCardDao vipCardDao;
    @Autowired
    private RideOrderDayStaDao rideOrderDayStaDao;
    @Autowired
    private DepositOrderDayStaDao depositOrderDayStaDao;
    @Autowired
    private RideCardOrderDayStaDao rideCardOrderDayStaDao;
    @Autowired
    private VipCardOrderDayStaDao vipCardOrderDayStaDao;
    @Autowired
    private RefundOpeLogDao RefundOpeLogDao;
    @Autowired
    private RechargeDao rechargeDao;
    @Resource
    private NewUserDayStaDao newUserDayStaDao;


    @Override
    public List<FinaStat> groupByAccountId(String accountIds, Long startTime, Long endTime, LoginInfo info) {
        List<FinaStat> list = new ArrayList<>();
        List<Integer> accountIdList = Arrays.stream(accountIds.split(",")).map(Integer::parseInt).collect(Collectors.toList());
        List<Account> accountList = accountDao.getByAccountIds(accountIdList);
        //初始化返回数据
        for (Account a : accountList) {
            FinaStat finaStat = new FinaStat(a.getName(), a.getAccountId(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0.0, 0, new ArrayList<>(), 0, 0);
            list.add(finaStat);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("startTime", new Date(startTime));
        map.put("endTime", new Date(endTime));
        map.put("accountIds", StringUtil.getListString(accountIdList));
        map.put("ids", accountIdList);
        //哈希存储收入信息*/
        Map<String, MoneyData> dataMap = new HashMap<>();
        Map<String, Object> deptMap = new HashMap<>();

        long runTime = System.currentTimeMillis();

        accountIdList.forEach(acc -> {
            Map<String, Object> map1 = new HashMap<>();
            map1.put("startTime", new Date(startTime));
            map1.put("endTime", new Date(endTime));
            map1.put("accountIds", acc);
            Map<String, Object> map2 = new HashMap<>();
            //日期是大于今天则加上今天产生的金额
            MoneyData moneyData;
            if (-1 != new Date(endTime).compareTo(new Date())) {
                //修改开始实际为昨天23:59:59
                map2.put("startTime", DateTimeUtil.getYesterdayHHMMSS(-1));
                map2.put("endTime", new Date(endTime));
                map2.put("accountIds", acc);
            }
            //获取免押收入
            Integer money = 0;
            Integer num = 0;
            List<MoneyData> memData1 = depositOrderDayStaDao.groupByAccountId(map1);
            List<MoneyData> memData = memberFeeDao.groupByAccountId(map2);
            if (null != memData) {
                money += memData.get(0).getMoney();
                num += memData.get(0).getNum();
            }
            if (null != memData1) {
                money += memData1.get(0).getMoney();
                num += memData1.get(0).getNum();
            }
            moneyData = new MoneyData(acc, money, num);
            dataMap.put("mem." + moneyData.getAccountId(), moneyData);
            //获取骑行收入
            money = 0;
            num = 0;
            List<MoneyData> rideData1 = rideOrderDayStaDao.groupByAccountId(map1);
            List<MoneyData> rideData = rideLogDao.groupByAccountId(map2);
            if (null != rideData) {
                money += rideData.get(0).getMoney();
                num += rideData.get(0).getNum();
            }
            if (null != rideData1) {
                money += rideData1.get(0).getMoney();
                num += rideData1.get(0).getNum();
            }
            moneyData = new MoneyData(acc, money, num);
            dataMap.put("ride." + moneyData.getAccountId(), moneyData);

            //获取骑行卡收入
            money = 0;
            num = 0;
            List<MoneyData> rideCardData1 = rideCardOrderDayStaDao.groupByAccountId(map1);
            List<MoneyData> rideCardData = rideCardDao.groupByAccountId(map2);
            if (null != rideCardData) {
                money += rideCardData.get(0).getMoney();
                num += rideCardData.get(0).getNum();
            }
            if (null != rideCardData1) {
                money += rideCardData1.get(0).getMoney();
                num += rideCardData1.get(0).getNum();
            }
            moneyData = new MoneyData(acc, money, num);
            dataMap.put("rideCard." + moneyData.getAccountId(), moneyData);
            //统计会员卡
            money = 0;
            num = 0;
            List<MoneyData> vipData1 = vipCardOrderDayStaDao.groupByAccountId(map1);
            List<MoneyData> vipData = vipCardDao.groupByAccountId(map2);
            if (null != vipData) {
                money += vipData.get(0).getMoney();
                num += vipData.get(0).getNum();
            }
            if (null != vipData1) {
                money += vipData1.get(0).getMoney();
                num += vipData1.get(0).getNum();
            }
            moneyData = new MoneyData(acc, money, num);
            dataMap.put("vip." + moneyData.getAccountId(), moneyData);

            //获取欠款总数和金额
            money = 0;
            num = 0;
            MoneyData debtData = rideLogDao.getDebtTotal(map1);
            money += debtData.getMoney();
            num += debtData.getNum();
            moneyData = new MoneyData(acc, money, num);
            dataMap.put("debtData." + moneyData.getAccountId(), moneyData);

            //获取欠款补交总数和金额
            money = 0;
            num = 0;
            MoneyData debtPayData = rideLogDao.getDebtPayTotal(map1);
            money += debtPayData.getMoney();
            num += debtPayData.getNum();
            moneyData = new MoneyData(acc, money, num);
            dataMap.put("debtPayData." + moneyData.getAccountId(), moneyData);
            //获取欠款补交详情*/
            List<DeptPayVO> deptPayVOList = rideLogDao.getDebtPayPage(map1);
            deptMap.put("deptPayVOList." + moneyData.getAccountId(), deptPayVOList);
        });
        //获取区域的充值记录
        Map<Integer, Map> rechargeMap = rechargeDao.sumGroupByAdAccountId(new Date(startTime), new Date(endTime), accountIdList);
        //退款总数
        map.put("flag", 1);
        List<MoneyData> refundData = RefundOpeLogDao.totalRideRefundOpeLog(map);
        for (MoneyData moneyData : refundData) {
            dataMap.put("refund." + moneyData.getAccountId(), moneyData);
        }
        //获取新增用户数 改为查询预统计
        List<MoneyData> newUserData = newUserDayStaDao.getByAccountId(map);
        for (MoneyData moneyData : newUserData) {
            dataMap.put("newUser." + moneyData.getAccountId(), moneyData);
        }
        //获取车辆总数
        List<MoneyData> MachineNumData = machineDao.groupByAccountId(map);
        for (MoneyData moneyData : MachineNumData) {
            dataMap.put("machine." + moneyData.getAccountId(), moneyData);
        }


        //组装数据
        for (FinaStat finaStat : list) {
            MoneyData mem = dataMap.get("mem." + finaStat.getAccountId());
            if (mem != null) {
                if (mem.getMoney() != null) {
                    finaStat.setMemMoney(mem.getMoney());
                }
                if (mem.getNum() != null) {
                    finaStat.setMemCount(mem.getNum());
                }
            }
            MoneyData ride = dataMap.get("ride." + finaStat.getAccountId());
            if (ride != null) {
                if (ride.getMoney() != null) {
                    finaStat.setRideMoney(ride.getMoney());
                }
                if (ride.getNum() != null) {
                    finaStat.setRideCount(ride.getNum());
                }
            }
            //vip会员卡
            MoneyData vip = dataMap.get("vip." + finaStat.getAccountId());
            if (vip != null) {
                if (vip.getMoney() != null) {
                    finaStat.setVipMoney(vip.getMoney());
                }
                if (vip.getNum() != null) {
                    finaStat.setVipCount(vip.getNum());
                }
            }
            MoneyData rideCard = dataMap.get("rideCard." + finaStat.getAccountId());
            if (rideCard != null) {
                if (rideCard.getMoney() != null) {
                    finaStat.setRideCardMoney(rideCard.getMoney());
                }
                if (rideCard.getNum() != null) {
                    finaStat.setRideCardCount(rideCard.getNum());
                }
            }
            MoneyData refund = dataMap.get("refund." + finaStat.getAccountId());
            if (refund != null) {
                if (refund.getMoney() != null) {
                    finaStat.setTotalMoneyRefund(refund.getMoney());
                }
                if (refund.getNum() != null) {
                    finaStat.setTotalNumberOfRefunds(refund.getNum());
                }
            }
            MoneyData newUser = dataMap.get("newUser." + finaStat.getAccountId());
            if (newUser != null) {
                finaStat.setNewUser(newUser.getNum());
            }
            MoneyData machine = dataMap.get("machine." + finaStat.getAccountId());
            if (machine != null) {
                finaStat.setMachineNum(machine.getNum());
            }
            //组装欠款数据*/
            MoneyData dept = dataMap.get("debtData." + finaStat.getAccountId());
            if (dept != null) {
                finaStat.setDept(Double.parseDouble(dept.getMoney().toString()));
                finaStat.setDeptNum(dept.getNum());
            }
            //组装欠款补交数据*/
            MoneyData deptPay = dataMap.get("debtPayData." + finaStat.getAccountId());
            if (deptPay != null) {
                finaStat.setDeptPay(Double.parseDouble(deptPay.getMoney().toString()));
                finaStat.setDeptPayNum(deptPay.getNum());
            }
            //组装欠款补交详情数据*/
            Object data = deptMap.get("deptPayVOList." + finaStat.getAccountId());
            if (data != null) {
                finaStat.setDeptPayVOList((List<DeptPayVO>) data);
            }
            //组装充值数据*/
            Integer adAccountId = finaStat.getAccountId();
            finaStat.setRechargeMoney(rechargeMap.get(adAccountId) == null ? 0 : Integer.parseInt(rechargeMap.get(adAccountId).get("money").toString()));
            finaStat.setRechargeNum(rechargeMap.get(adAccountId) == null ? 0 : Integer.parseInt(rechargeMap.get(adAccountId).get("count").toString()));
        }

        log.info("组装数据获取运行时间：{}毫秒", (System.currentTimeMillis() - runTime));

        return list;
    }


    @Override
    public List<WeixinDepositLog> queryPage(Integer accountId, Long startTime, Long endTime,
                                            Integer pageNO, Integer rowCount) {
        Map<String, Object> params = new HashMap<>(8);
        params.put("accountId", accountId);
        if (startTime != null) {
            params.put("startTime", new Date(startTime));
        }
        if (endTime != null) {
            params.put("endTime", new Date(endTime));
        }
        params.put("page", (pageNO - 1) * rowCount);
        params.put("rowCount", rowCount);
        return weixinDepositLogDao.queryPage(params);
    }

    @Override
    public Integer queryCount(Integer accountId, Long startTime, Long endTime) {
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        if (startTime != null) {
            params.put("startTime", new Date(startTime));
        }
        if (endTime != null) {
            params.put("endTime", new Date(endTime));
        }
        return weixinDepositLogDao.queryCount(params);
    }

    @Override
    public List<WeixinDepositLog> export(Integer accountId, Long startTime, Long endTime) {
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        if (startTime != null) {
            params.put("startTime", new Date(startTime));
        }
        if (endTime != null) {
            params.put("endTime", new Date(endTime));
        }
        return weixinDepositLogDao.export(params);
    }

    @Override
    public JSONObject getSum(Integer accountId, Long startTime, Long endTime) {
        Map<String, Object> params = new HashMap<>();
        params.put("accountId", accountId);
        if (startTime != null) {
            params.put("startTime", new Date(startTime));
        }
        if (endTime != null) {
            params.put("endTime", new Date(endTime));
        }
        Map<String, Object> map = weixinDepositLogDao.getSum(params);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("returnMoney", map.get("returnMoney"));
        jsonObject.put("returnCount", map.get("returnCount"));
        jsonObject.put("money", map.get("money"));
        jsonObject.put("count", map.get("count"));
        return jsonObject;
    }

    @Override
    @EncapsulateMap
    public List<WeixinDepositLog> getDepositByArea(HashMap<String, Object> params, Integer accountId, Long startTime, Long endTime, Integer rowCount, Integer pageNO, Boolean isPage) {
        if (isPage) {
            PageHelper.startPage(pageNO, rowCount);
        }
        return weixinDepositLogDao.getDepositByArea(params);
    }

    @Override
    @EncapsulateMap
    public int getDepositCountByArea(HashMap<Object, Object> params, Integer accountId, Long startTime, Long endTime) {
        return weixinDepositLogDao.getDepositCountByArea(params);
    }
}
